class AliAnalysisGrid;
const char *dataset   = "";
TString anaLibs = "";
//Int_t iESDfilter       = 1;
Int_t iESDfilter       = 0;
Int_t iAODTagCreation  = 1;
Int_t iAODAddMCBranch  = 0;

//______________________________________________________________________________
void run(
         const char* runtype = "grid", // local, proof or grid
	 const char *gridmode = "test", // Set the run mode (can be "full", "test", "offline", "submit" or "terminate"). Full & Test work for proof
         const bool bMCtruth = 1, // 1 = MCEvent handler is on (MC truth), 0 = MCEvent handler is off (MC reconstructed/real data)
         const bool bMCphyssel = 1, // 1 = looking at MC truth or reconstructed, 0 = looking at real data
         const Long64_t nentries = 2000, // for local and proof mode, ignored in grid mode. Set to 1234567890 for all events.
         const Long64_t firstentry = 0, // for local and proof mode, ignored in grid mode
         const char *proofdataset = "/alice/data/LHC10c_000120821_p1", // path to dataset on proof cluster, for proof analysis
         const char *proofcluster = "alice-caf.cern.ch", // which proof cluster to use in proof mode
	 const char *taskname = "NanoAOD_PbPb2011"
         )
{
  // check run type
  if(runtype != "local" && runtype != "proof" && runtype != "grid"){
    Printf("\n\tIncorrect run option, check first argument of run macro");
    Printf("\tint runtype = local, proof or grid\n");
    return;
  }
  Printf("%s analysis chosen",runtype);
  
  gROOT->ProcessLine(".include $ALICE_ROOT/include");

  gSystem->AddIncludePath("-I$ALICE_ROOT/include");
  gSystem->AddIncludePath("-I$ALICE_ROOT/PWGHF/vertexingHF"); 
  // Load analysis specific libraries
  //=====================================================================
    
  gSystem->SetIncludePath("-I. -I$ROOTSYS/include -I$ALICE_ROOT -I$ALICE_ROOT/include -I$ALICE_ROOT/ITS -I$ALICE_ROOT/TPC -I$ALICE_ROOT/CONTAINERS -I$ALICE_ROOT/STEER/STEER -I$ALICE_ROOT/STEER/STEERBase -I$ALICE_ROOT/STEER/ESD -I$ALICE_ROOT/STEER/AOD -I$ALICE_ROOT/TRD -I$ALICE_ROOT/macros -I$ALICE_ROOT/ANALYSIS  -I$ALICE_ROOT/OADB -I$ALICE_ROOT/PWGHF -I$ALICE_ROOT/PWGHF/base -I$ALICE_ROOT/PWGHF/vertexingHF -I$ALICE_ROOT/PWG/FLOW/Base -I$ALICE_ROOT/PWG/FLOW/Tasks -g"); 
  
  gSystem->Load("libTree.so");
  gSystem->Load("libGeom.so");
  gSystem->Load("libPhysics.so");
  gSystem->Load("libVMC.so");
  gSystem->Load("libMinuit.so");
  gSystem->Load("libSTEERBase.so");
  gSystem->Load("libESD.so");
  gSystem->Load("libAOD.so"); 
  gSystem->Load("libANALYSIS.so");
  gSystem->Load("libOADB.so");
  gSystem->Load("libANALYSISalice.so");
  gSystem->Load("libCORRFW.so");
  gSystem->Load("libPWGHFbase.so");
  gSystem->Load("libPWGflowBase.so");
  gSystem->Load("libPWGflowTasks.so");
  gSystem->Load("libPWGHFvertexingHF.so");
  
  // Load analysis specific libraries
  //=====================================================================
  //------ Create AlienPlugin ---------------------

  AliAnalysisGrid *plugin = CreateAlienHandler(taskname, gridmode, proofcluster, proofdataset); 
  if(!plugin) return;

        
  //---- Create the analysis manager
  AliAnalysisManager* mgr = new AliAnalysisManager(taskname);
  mgr->SetGridHandler(plugin);

  //  Input

  AliAODInputHandler* iH = new AliAODInputHandler("handler","handler for my analisys");
  mgr->SetInputEventHandler(iH);

  AliAODHandler* aodOutputHandler = new AliAODHandler();
  aodOutputHandler->SetOutputFileName("AliAOD.Muons.root");
  mgr->SetOutputEventHandler(aodOutputHandler);
  //--------------------------------------------------------------
  // Task Aggiuntivi

  // gROOT->LoadMacro("$ALICE_ROOT/ANALYSIS/macros/AddTaskPhysicsSelection.C");
  // AliPhysicsSelectionTask *physSelTask = AddTaskPhysicsSelection(bMCphyssel);
  // if(!physSelTask) { Printf("no physSelTask"); return; }

  // PID Task
  
  gROOT->ProcessLine(".L $ALICE_ROOT/ANALYSIS/macros/AddTaskPIDResponse.C");
  AliAnalysisTask *PIDTask = AddTaskPIDResponse(kFALSE,kTRUE);
  if(!PIDTask ) { Printf("no physSelTask"); return; }
    
  if (iESDfilter) {
    AliAnalysisTaskESDfilter *esdfilter = AddTaskESDFilter(useKFILTER);
    
    if (iAODTagCreation) {
      // use this line if AddTaskTagCreation.C is available in the grid aliroot version
      if(!strcmp(analysisMode, "LOCAL")){
	gROOT->LoadMacro("AddTaskTagCreation.C");
      } else  {
	// uncomment  this line if AddTaskTagCreation.C is available in the grid aliroot version
	//   	  gROOT->LoadMacro("$ALICE_ROOT/PWG3/muon/AddTaskTagCreation.C");
	// otherwise temporary: (and AddTaskTagCreation.C must be also added in the jdl)
	gROOT->LoadMacro("AddTaskTagCreation.C");
      }	 
      AliAnalysisTaskTagCreator *tagcreator = AddTaskTagCreation();
    }       
  }  
  

  else{
    
    cout<<"##################### ELSE ######################"<<endl;

    Bool_t onlyMuon=kTRUE;
    Bool_t keepAllEvents=kTRUE;
    //      Int_t mcMode= useKineFilter ? muonMCMode : 0; // use 1 instead of 2 to get all MC information instead of just ancestors of mu tracks
    Int_t mcMode =0 ;
    //Define the PID track cuts
      
    Int_t nsigmaTrk1 = 3;
    Int_t partType1 = 2;
    Int_t nsigmaTrk2 = 5; 
    Int_t partType2 = 7;
      
    // gROOT->LoadMacro("/home/ramona/ANALISI/TestRiduzione/NewTask/TipoMuoni/Test1/041213_CodiceVecchioLeggiAOD/AliAODMuonReplicator0.cxx++g");
    // gROOT->LoadMacro("/home/ramona/ANALISI/TestRiduzione/NewTask/TipoMuoni/Test1/041213_CodiceVecchioLeggiAOD/AliAnalysisTaskESDMuonFilterO.cxx++g");
    
    cout<<"##################### 1 ######################"<<endl;

    
    gROOT->LoadMacro("AliAODMuonReplicator0.cxx++g");
    gROOT->LoadMacro("AliAnalysisTaskESDMuonFilterO.cxx++g");

    cout<<"##################### 2 ######################"<<endl;
    AliAnalysisTaskESDMuonFilterO *esdmuonfilter = new AliAnalysisTaskESDMuonFilterO("ESD Muon Filter",onlyMuon,keepAllEvents,mcMode,nsigmaTrk1,partType1,nsigmaTrk2,partType2);
    
    // esdmuonfilter->SelectCollisionCandidates(AliVEvent::kMB || AliVEvent::kCentral || AliVEvent::kSemiCentral  ); // if physics selection performed in UserExec(), this line should be commented        

    mgr->AddTask(esdmuonfilter);
    esdmuonfilter->SetWriteMuonAOD(kTRUE);

    cout<<"##################### 3 ######################"<<endl;
     
    mgr->ConnectInput  (esdmuonfilter,  0, mgr->GetCommonInputContainer());
    mgr->ConnectOutput (esdmuonfilter,  0, mgr->GetCommonOutputContainer());
     
  
  }
  // enable debug printouts
  mgr->SetDebugLevel(2);
  if (!mgr->InitAnalysis()) return;
  mgr->PrintStatus();
  
  // start analysis
  Printf("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Starting Analysis....");
  mgr->StartAnalysis(runtype,nentries,firstentry);
}

//______________________________________________________________________________
AliAnalysisGrid* CreateAlienHandler(const char *taskname, const char *gridmode, const char *proofcluster, const char *proofdataset)
{
    AliAnalysisAlien *plugin = new AliAnalysisAlien();
    // Set the run mode (can be "full", "test", "offline", "submit" or "terminate")
    plugin->SetRunMode(gridmode);

    // Set versions of used packages
  
    plugin->SetAPIVersion("V1.1x");
    plugin->SetROOTVersion("v5-34-08");
    plugin->SetAliROOTVersion("v5-05-25-AN");
    plugin->SetExecutableCommand("aliroot -b -q");

    // Declare input data to be processed.

    // Method 1: Create automatically XML collections using alien 'find' command.
    // Define production directory LFN
    //    plugin->SetGridDataDir("/alice/data/2010/LHC10h");
 
    // plugin->SetGridDataDir(" /alice/data/2011/LHC11h_2/"); //sim
    // plugin->SetDataPattern("pass2/*AliAOD.root"); // sim

    plugin->SetGridDataDir("/alice/data/2011/LHC11h_2/"); //sim
    plugin->SetDataPattern("/pass2/AOD142/*AliAOD.root"); // sim
    plugin->SetRunPrefix("000");   // real data

    Int_t runlist[1]={167693};
    for(Int_t i=0;i<1;i++)
      plugin->AddRunNumber(runlist[i]);
    
    //    plugin->AddRunNumber(139505);
    //  plugin->AddRunNumber(138652);
    plugin->SetNrunsPerMaster(1);
    plugin->SetOutputToRunNo();
    
    
    // Method 2: Declare existing data files (raw collections, xml collections, root file)
    //   plugin->AddDataFile("/alice/data/2008/LHC08c/000057657/raw/Run57657.Merged.RAW.tag.root");

    // Define alien work directory where all files will be copied. Relative to alien $HOME.
    plugin->SetGridWorkingDir(taskname);

    // Declare alien output directory. Relative to working directory.
    plugin->SetGridOutputDir("output"); // In this case will be $HOME/taskname/out

    //  plugin->SetAdditionalLibs("libTree.so libGeom.so libPhysics.so libVMC.so libMinuit.so libSTEERBase.so libESD.so libAOD.so  libANALYSIS.so libOADB.so libANALYSISalice.so libCORRFW.so libPWGHFbase.so libPWGflowBase.so libPWGflowTasks.so libPWGHFvertexingHF.so");

    // plugin->SetAdditionalLibs("libCORRFW.so libPWGHFbase.so libPWGflowBase.so libPWGflowTasks.so libPWGHFvertexingHF.so");

    plugin->SetAnalysisSource("AliAODMuonReplicator0.cxx AliAnalysisTaskESDMuonFilterO.cxx");
  
    plugin->SetAdditionalLibs("AliAnalysisTaskESDMuonFilterO.h AliAnalysisTaskESDMuonFilterO.cxx AliAODMuonReplicator0.h AliAODMuonReplicator0.cxx libTree.so libGeom.so libPhysics.so libVMC.so libMinuit.so libSTEERBase.so libESD.so libAOD.so libANALYSIS.so libOADB.so libANALYSISalice.so libCORRFW.so libPWGHFbase.so libPWGflowBase.so libPWGflowTasks.so libPWGHFvertexingHF.so");


    cout<<"-->>>>>>>>>>>>>>>>>>>>>>>>> 1"<<endl;

    // Declare the analysis source files names separated by blancs. To be compiled runtime
    // using ACLiC on the worker nodes.
  
    // Declare all libraries (other than the default ones for the framework. These will be
    // loaded by the generated analysis macro. Add all extra files (task .cxx/.h) here.
    // plugin->SetAdditionalLibs("AliAODMuonReplicator0_cxx.so");
    // plugin->SetAdditionalLibs("AliAnalysisTaskESDMuonFilterO_cxx.so");

    //questo
    //plugin->SetAdditionalLibs("libPWGflowBase.so libPWGflowTasks.so libPWGHFbase.so libPWGHFvertexingHF.so"); // this
    plugin->AddIncludePath("-I. -I$ROOTSYS/include -I$ALICE_ROOT -I$ALICE_ROOT/include -I$ALICE_ROOT/ITS -I$ALICE_ROOT/TPC -I$ALICE_ROOT/CONTAINERS -I$ALICE_ROOT/STEER/STEER -I$ALICE_ROOT/STEER/STEERBase -I$ALICE_ROOT/STEER/ESD -I$ALICE_ROOT/STEER/AOD -I$ALICE_ROOT/TRD -I$ALICE_ROOT/macros -I$ALICE_ROOT/ANALYSIS  -I$ALICE_ROOT/OADB -I$ALICE_ROOT/PWGHF -I$ALICE_ROOT/PWGHF/base -I$ALICE_ROOT/PWGHF/vertexingHF -I$ALICE_ROOT/PWG/FLOW/Base -I$ALICE_ROOT/PWG/FLOW/Tasks -g");


    // plugin->SetAdditionalLibs("AliAODMuonReplicator0.h AliAODMuonReplicator0.cxx");
    // plugin->SetAdditionalLibs("AliAnalysisTaskESDMuonFilterO.h AliAnalysisTaskESDMuonFilterO.cxx");

    //plugin->SetAdditionalLibs("AliAODMuonReplicator0.h AliAODMuonReplicator0.cxx AliAnalysisTaskESDMuonFilterO.h AliAnalysisTaskESDMuonFilterO.cxx");

    cout<<"-->>>>>>>>>>>>>>>>>>>>>>>>> 3"<<endl;
	
    // plugin->SetAdditionalLibs("AliAODMuonReplicator0.h AliAODMuonReplicator0.cxx");
    
    // plugin->SetAdditionalLibs("AliAnalysisTaskESDMuonFilterO.h AliAnalysisTaskESDMuonFilterO.cxx");

    // Declare the output file names separated by blancs.
    // (can be like: file.root or file.root@ALICE::Niham::File)
    // To only save certain files, use SetDefaultOutputs(kFALSE), and then
    // SetOutputFiles("list.root other.filename") to choose which files to save
    plugin->SetDefaultOutputs();
    //plugin->SetOutputFiles("list.root");

    // Optionally set a name for the generated analysis macro (default MyAnalysis.C)
    plugin->SetAnalysisMacro(Form("%s.C",taskname));

    // Optionally set maximum number of input files/subjob (default 100, put 0 to ignore)
    plugin->SetSplitMaxInputFileNumber(100);

    // Optionally modify the executable name (default analysis.sh)
    plugin->SetExecutable(Form("%s.sh",taskname));

    // set number of test files to use in "test" mode
   plugin->SetNtestFiles(10);

    // Optionally resubmit threshold.
    plugin->SetMasterResubmitThreshold(90);

    // Optionally set time to live (default 30000 sec)
    plugin->SetTTL(30000);

    // Optionally set input format (default xml-single)
    plugin->SetInputFormat("xml-single");

    // Optionally modify the name of the generated JDL (default analysis.jdl)
    plugin->SetJDLName(Form("%s.jdl",taskname));

    // Optionally modify job price (default 1)
    plugin->SetPrice(1);      

    // Optionally modify split mode (default 'se')    
    plugin->SetSplitMode("se");
    
    //----------------------------------------------------------
    //---      PROOF MODE SPECIFIC SETTINGS         ------------
    //---------------------------------------------------------- 
    // Proof cluster
    plugin->SetProofCluster(proofcluster);
    // Dataset to be used   
    plugin->SetProofDataSet(proofdataset);
    // May need to reset proof. Supported modes: 0-no reset, 1-soft, 2-hard
    plugin->SetProofReset(0);
    // May limit number of workers
    plugin->SetNproofWorkers(0);
    // May limit the number of workers per slave
    plugin->SetNproofWorkersPerSlave(1);   
    // May use a specific version of root installed in proof
    plugin->SetRootVersionForProof("current");
    // May set the aliroot mode. Check http://aaf.cern.ch/node/83 
    plugin->SetAliRootMode("default"); // Loads AF libs by default
    // May request ClearPackages (individual ClearPackage not supported)
    plugin->SetClearPackages(kFALSE);
    // Plugin test mode works only providing a file containing test file locations, used in "local" mode also
    plugin->SetFileForTestMode("files.txt"); // file should contain path name to a local directory containg *ESDs.root etc
    // Request connection to alien upon connection to grid
    plugin->SetProofConnectGrid(kFALSE);
    
    cout<<"-->>>>>>>>>>>>>>>>>>>>>>>>> 4"<<endl;
	

    return plugin;
    
    cout<<"-->>>>>>>>>>>>>>>>>>>>>>>>> 5"<<endl;
	
}

